/**
 * Copyright (c) suzuki ryoutoku
 * See this code regarding the Apache License Version 2.0
 * @file main.cpp
 * @author suzuki ryoutoku
 */

//=============================================================================
//	Preporcessor
//=============================================================================
#include "GlobalParameter.h"
#include "CallBack.h"

//=============================================================================
//	Declare function
//=============================================================================
// This function is equiped in thread.
void* thread_function(void* args);

void TestFunction(library::graphics::Screen* screen);

// This function creates main window.
GtkWidget* CreateMainWindow(void);

// This function creates menu bar.
GtkWidget* CreateMenuBar(void);

bool ShowMessageBox(std::string title, std::string message);


//=============================================================================
//	Global parameter
//=============================================================================
/**
 * For debug, test 3d draw command.
 * @author r-suzuki
 * @date 2007-10-8
 * @version 1.0
 */
TestCommand* g_test_command;


//=============================================================================
//	Defin function
//=============================================================================
/**
 * Application's entry point
 * @author name
 * @date 2007-7-21
 * @version 1.0
 */
int main(int argc, char* argv[])
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  gp->initializeaLogManager();

  //Initialize gthread
  g_thread_init(NULL);
  gdk_threads_init();

  //Initialize gtk & parse application's argument.
  gtk_init(&argc,&argv);
  gtk_set_locale();

  //Creating root window.
  gp->setM_main_window(CreateMainWindow());

  //Create vertical packing
  GtkWidget* vbox = gtk_vbox_new(FALSE, 2);
  gtk_container_add(GTK_CONTAINER(gp->getM_main_window()), vbox);

  //Insert menu to vertical packing window
  gtk_box_pack_start(GTK_BOX(vbox), CreateMenuBar(), FALSE, FALSE, 0);

  //Create horizon packing widget
  GtkWidget* hbox = gtk_hbox_new(FALSE, 2);
  // Insert horizon packing widget to vertical packing widget
  gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);

  //Create Hierarchy view window
  gp->createHierarchyViewWindow();

  //Create Attribute view window 
  gp->createAttributeViewWindow();

  //Create Notebook widget and Insert Notebook widget to horizon packing widget
  gp->createNotebook(hbox);
  
  //Create draw area
  gp->createDrawArea(hbox);

  // Create background
  gp->createBackground();

  // create default data
  gp->createDefaultData();

  // initialize hierarcy tree view
  gp->initializeTreeView();

  // initialize drawing string
  gp->createDrawingString();

  gtk_widget_show_all(gp->getM_main_window());

#if 0 //test command
  TestCommand* test = new TestCommand();
  test->setOriginalFunction(TestFunction);
  gp->getM_rm()->getM_screen(0)->registGraphicalCommand(test);
#endif

  // thread safety 
  gdk_threads_enter();
  {
	gtk_main();
  }
  gdk_threads_leave();

  return 0;
}

/**
 * Callback for file chooser dialog's ok button
 * \note
 * @param w this is button widget
 * @param fs dialog
 * @author suzuki ryoutoku
 * @date 2007-8-3
 * @version 1.0
 */
void inputfile_ok_sel(GtkWidget *w, GtkFileSelection *fs)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  GtkTreeStore* store 
	= GTK_TREE_STORE(gtk_tree_view_get_model(gp->getM_hierarchyview()));
  GtkTreeStore* store_attributeview 
	  = GTK_TREE_STORE(gtk_tree_view_get_model(gp->getM_attributeview()));
  
  char* tmp= (char*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs));

  // dispatch file chooser dialog
  gtk_widget_destroy((GtkWidget*)fs);


  if( gp->getM_model() != NULL ){
	gp->releaseModelData();
	gtk_tree_store_clear(store);
	gtk_tree_store_clear(store_attributeview);

	// clear mouse coordinate
	gp->resetMouseCoordinate();
  }

  // reinitialize menu item
  gtk_check_menu_item_set_active((GtkCheckMenuItem*)gp->getM_line_menu(), 
								 FALSE);
  gtk_check_menu_item_set_active((GtkCheckMenuItem*)gp->get_check_selectvert(),
								 FALSE);
  gtk_check_menu_item_set_active((GtkCheckMenuItem*)gp->get_check_selectpoly(),
								 FALSE);


  // Copy string to represent data directory 
  gp->set_data_directory(tmp);
  for( int i = strlen(gp->get_data_directory()) -1; i > 0 ;i -- ){
	if( gp->get_data_directory()[i] == '/' ){
	  break;
	}else{
	  gp->get_data_directory()[i] = '\0';
	}
  }

  // read file
  string filename(tmp);
  Reader* reader = Reader::CreateReader(filename, LogManager::GetInstance());
  if( reader == NULL ){
	ShowMessageBox(std::string(" Error"),
				   std::string("error !! can not read file..."));
	return;
  }
  gp->setM_model( reader->read(filename) );
  gp->readTextureFile(reader);
  delete reader;

  // initialize model data
  if( gp->getM_model() != NULL ){
	gp->getM_model()->setTextureID(ImageDataManager::getInstance());
	gp->initializeModelData();
  }

  // if error occur!
  if( gp->getM_model() == NULL ){
	ShowMessageBox(std::string(" Error"),
				   std::string("error !! can not read file..."));
	return;
  }

  // setting tree view
  gp->initializeTreeView();

  // setting attribute view
  gp->initializeAttributeView(store_attributeview, false);

  char message[256];
  sprintf(message,
		  "polygon sum = %d vertex sum = %d",
		  gp->getM_model()->get_polygon_sum(),
		  gp->getM_model()->get_vertex_sum());
  gp->getM_shapeinformation()->setM_message(message);

  // publish draw command
  gtk_widget_queue_draw(GTK_WIDGET(gp->getM_main_window()));
}

/**
 * Output pcm file method.
 * @author suzuki ryoutoku
 * @version 1.0
 * @date 2008-6-23
 */
void outputpcmfile_ok_sel(GtkWidget *w, GtkFileSelection *fs)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  char* tmp= (char*)gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs) );
  library::graphics::Writer writer(tmp);
  writer.outputPCM(gp->getM_model());
  cout << tmp << endl;
  gtk_widget_destroy((GtkWidget*)fs);
}

/**
 * Output vdf file.
 * @author r-suzuki
 * @date 2008-12-7
 * @version 1.0
 */
void outputvdffile_ok_sel(GtkWidget *w, GtkFileSelection *fs)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  char* tmp= (char*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs));
  library::graphics::Writer writer(tmp);
  writer.outputVDF(gp->getM_model());
  cout << tmp << endl;
  gtk_widget_destroy((GtkWidget*)fs);
}

/**
 * Callback of event to press pressing cancel button in file chooser dialog.
 * @author suzuki ryoutoku
 * @date 2007-8-24
 * @version 1.0
 */
void file_cancel_sel(GtkWidget *w, GtkFileSelection *fs)
{
  gtk_widget_destroy((GtkWidget*)fs);
}

/**
 * Callback of event press menu items
 * \note
 * This function is multiple items.
 * Multiple menu items are open menu, about menu, lighting menu.
 * @param string when this function registed, sepcify param.
 * @author suzuki ryoutoku
 * @date 2007-8-3
 * @version 1.0
 */
void cb_menuitem_response(gchar* string)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  if( NULL != strstr((char*)string,OPEN_3DSFILE_MENU) || 
	  NULL != strstr((char*)string,OPEN_PCMFILE_MENU) || 
	  NULL != strstr((char*)string,OPEN_VDFFILE_MENU) ){
	// get user's home directory
	chdir(gp->get_data_directory());
	GtkWidget* file_select 
	  = gtk_file_selection_new(string);
	if( NULL != strstr((char*)string,OPEN_3DSFILE_MENU) ){
	  gtk_file_selection_complete(GTK_FILE_SELECTION(file_select),
								  "*.3ds");
	}else if( NULL != strstr((char*)string,OPEN_VDFFILE_MENU) ){
	  gtk_file_selection_complete(GTK_FILE_SELECTION(file_select),
								  "*.vdf");
	}else{
	  gtk_file_selection_complete(GTK_FILE_SELECTION(file_select),
								  "*.pcm");
	}

	
	/* equip inputfile_ok_sel with ok_button */
	gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(file_select)->ok_button),
					   "clicked", 
					   (GtkSignalFunc)inputfile_ok_sel, 
					   file_select );
	// push cancel button
	gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION
								  (file_select)->cancel_button),
					   "clicked",
					   (GtkSignalFunc)file_cancel_sel,
					   file_select );

	gtk_window_set_modal(GTK_WINDOW(file_select),TRUE);
	gtk_widget_show(file_select);
	
  }else if( NULL != strstr((char*)string, SUB_MENU_OUTPUT_PCMFILE) || 
			NULL != strstr((char*)string, SUB_MENU_OUTPUT_VDFFILE) ){
	chdir(gp->get_data_directory());
	GtkWidget* file_select 
	  = gtk_file_selection_new(string);
	if( NULL != strstr((char*)string, SUB_MENU_OUTPUT_VDFFILE) ){
	  gtk_file_selection_complete(GTK_FILE_SELECTION(file_select),
								"*.vdf");
	  gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_select),
									  "output.vdf");
	  /* equip inputfile_ok_sel with ok_button */
	  gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(file_select)->ok_button),
						 "clicked", 
						 (GtkSignalFunc)outputvdffile_ok_sel, 
						 file_select);
	}else{
	  gtk_file_selection_complete(GTK_FILE_SELECTION(file_select),
								  "*.pcm");
	  gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_select),
									  "output.pcm");
	  /* equip inputfile_ok_sel with ok_button */
	  gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(file_select)->ok_button),
						 "clicked", 
						 (GtkSignalFunc)outputpcmfile_ok_sel, 
						 file_select);
	}
	
	// push cancel button
	gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION
								  (file_select)->cancel_button),
					   "clicked",
					   (GtkSignalFunc)file_cancel_sel,
					   file_select );

	gtk_window_set_modal(GTK_WINDOW(file_select),TRUE);
	gtk_widget_show(file_select);

  }else if( NULL != strstr((char*)string,SUB_MENU_ABOUT_STRIPEXPERIMENT) ){
	// Help => about menu callback
	const gchar *authors[] = {AUTHOR,NULL};
	gtk_show_about_dialog(GTK_WINDOW(gp->getM_main_window()),
						  "authors",authors,
						  "version", APPLICATION_VERSION,
						  "license", LICENSE,
						  "website", WEBSITE,
						  "copyright",COPYRIGHT,
						  NULL);


  }else if( NULL != strstr((char*)string,SUB_MENU_SETTING_LIGHT_PARAMETER) ){
	// Display => setting light parameter's callback
	GtkWidget* dialog 
	  = gtk_dialog_new_with_buttons("Setting light parameter",
									GTK_WINDOW(gp->getM_main_window()),
									(GtkDialogFlags)(GTK_DIALOG_MODAL |
									GTK_DIALOG_DESTROY_WITH_PARENT),
									GTK_STOCK_NO,
									GTK_RESPONSE_NO,
									GTK_STOCK_YES,
									GTK_RESPONSE_YES,
									NULL
									);
	// lighting ON/OFF
	GtkWidget* hbox = gtk_hbox_new(FALSE, 2);
	GtkWidget* light_on = gtk_radio_button_new_with_label(NULL,
														  "light on");
	gtk_box_pack_start(GTK_BOX(hbox), light_on, GL_TRUE, GL_TRUE, 0);
	GtkWidget* light_off 
	  = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(light_on),
													"light off");
	// initialize 3d model data's lighting parameter
	if( gp->getM_model()->GraphicalCommand::getM_state() 
		& GraphicalCommand::LIGHTING){
	  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(light_on), TRUE);
	}else{
	  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(light_off), TRUE);
	}

	gtk_box_pack_start(GTK_BOX(hbox), light_off, GL_TRUE, GL_TRUE, 0);
	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox) , hbox);
	

	// dialog run
	gtk_widget_show_all(dialog);
	gint response = gtk_dialog_run(GTK_DIALOG(dialog));

	// accept user input
	if( response == GTK_RESPONSE_YES ){
	  // user input of radio button
	  gboolean off_active 
		= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(light_off));

	  if( off_active == TRUE){
		gp->getM_model()->setM_state(gp->getM_model()->getM_state()
									 -GraphicalCommand::LIGHTING);
	  }else{
		gp->getM_model()->setM_state(gp->getM_model()->getM_state()
									 |GraphicalCommand::LIGHTING);
	  }
	}
	// dispatch dialog
	gtk_widget_destroy(dialog);
#ifdef DEBUG
	cout << "dialog end" << endl;
#endif

  }else if( NULL != strstr((char*)string,SUB_MENU_RESET_COORDINATE) ){

	// Display => reset coordinate's callback
	Matrix<double> matrix;
	gp->getM_model()->getM_coordinate()->setM_matrix(matrix);
	gp->getM_model()->getM_coordinate()->setM_pivot(Vector<double>(0.0,
																   0.0,
																   0.0,
																   0.0));


  }else if( NULL != strstr((char*)string,SUB_MENU_SCALING) ){
	
	// Display => scaling's callback
	GtkWidget* dialog 
	  = gtk_dialog_new_with_buttons("Scaling",
									GTK_WINDOW(gp->getM_main_window()),
									(GtkDialogFlags)(GTK_DIALOG_MODAL |
									GTK_DIALOG_DESTROY_WITH_PARENT),
									NULL
									);
	gtk_widget_set_size_request(dialog,
								250,
								120);

	GtkAdjustment* adjustment;
	GtkWidget* scale;
	adjustment  = (GtkAdjustment*)gtk_adjustment_new(1.0, 
													 0.01, 
													 10.0,
													 0.01, 
													 1.0,
													 0.0);
	scale = gtk_hscale_new(adjustment);
	gtk_scale_set_digits(GTK_SCALE(scale), 2);
	gtk_scale_set_draw_value(GTK_SCALE(scale), TRUE);
	gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_BOTTOM);
	g_signal_connect(GTK_SCALE(scale),
					 "value-changed",
					 G_CALLBACK(cb_scaling),
					 (void*)0x00);
	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox) , scale);
	adjustment  = (GtkAdjustment*)gtk_adjustment_new(1.0, 
													 0.01, 
													 10.0,
													 0.01, 
													 1.0,
													 0.0);
	scale = gtk_hscale_new(adjustment);
	gtk_scale_set_digits(GTK_SCALE(scale), 2);
	gtk_scale_set_draw_value(GTK_SCALE(scale), TRUE);
	gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_BOTTOM);
	g_signal_connect(GTK_SCALE(scale),
					 "value-changed",
					 G_CALLBACK(cb_scaling),
					 (void*)0x01);
	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox) , scale);
	adjustment  = (GtkAdjustment*)gtk_adjustment_new(1.0, 
													 0.01, 
													 10.0,
													 0.01, 
													 1.0,
													 0.0);
	scale = gtk_hscale_new(adjustment);
	gtk_scale_set_digits(GTK_SCALE(scale), 2);
	gtk_scale_set_draw_value(GTK_SCALE(scale), TRUE);
	gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_BOTTOM);
	g_signal_connect(GTK_SCALE(scale),
					 "value-changed",
					 G_CALLBACK(cb_scaling),
					 (void*)0x02);
	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox) , scale);
	
	// dialog run
	gtk_widget_show_all(dialog);
	gint response = gtk_dialog_run(GTK_DIALOG(dialog));
  }else if( NULL != strstr((char*)string, SUB_MENU_CREATE_TRIANGLESTRIP) ){
	// create strip
	if( gp->getM_model() == NULL ) return;
	GtkDialogFlags gdflag = 
	  (GtkDialogFlags)(GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT);
	GtkWindow* window = GTK_WINDOW(gp->getM_main_window());
	// show dialog to input parameter
	{
	  GtkWidget* dialog 
		= gtk_dialog_new_with_buttons("Setting strip parameter",
									  window,
									  gdflag,
									  GTK_STOCK_NO,
									  GTK_RESPONSE_NO,
									  GTK_STOCK_YES,
									  GTK_RESPONSE_YES,
									  NULL);
	  GtkWidget* hbox = gtk_hbox_new(FALSE, 2);
	  GtkWidget* io = gtk_radio_button_new_with_label(NULL,
													  "IO order");
	  gtk_box_pack_start(GTK_BOX(hbox), io, GL_TRUE, GL_TRUE, 0);
	  GtkWidget* degree 
		= gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(io),
													  "Less than degree");
	  gtk_box_pack_start(GTK_BOX(hbox), degree, GL_TRUE, GL_TRUE, 0);
	  GtkWidget* density
		= gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(io),
													  "Density");
	  gtk_box_pack_start(GTK_BOX(hbox), density, GL_TRUE, GL_TRUE, 0);
	  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox) , hbox);
	  gtk_widget_show_all(dialog);
	  gint response = gtk_dialog_run(GTK_DIALOG(dialog));
	  // accept user input
	  if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(io)) ){
		gp->set_strip_start_select(IO_ORDER);
	  }else if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(degree)) ){
		gp->set_strip_start_select(ADJACENCE_DEGREE);
	  }else if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(density)) ){
		gp->set_strip_start_select(DENSITY_DEGREE);
	  }
	  gtk_widget_destroy(dialog);
	  if( response == GTK_RESPONSE_NO ) return;
	}
	
	gp->getM_model()->removeTriangleStripCluster();
	gdflag = GTK_DIALOG_DESTROY_WITH_PARENT;
	GtkWidget* dialog = gtk_dialog_new_with_buttons("Create triangle strip",
													window,
													gdflag,
													NULL);
	GtkWidget* progressbar = gtk_progress_bar_new();
	gtk_box_pack_start((GtkBox *)((GtkDialog*)dialog)->vbox,
					   progressbar, 
					   FALSE,
					   FALSE,
					   0);
	gtk_widget_show_all(dialog);
	
	gp->setM_progress_dialog(dialog);
	gp->setM_progress((GtkProgressBar*)progressbar);
	gdk_flush();

	gp->setM_strip_counter(0);

	// after get return value
	GError *error = NULL;
	g_thread_create(thread_function, NULL, TRUE, &error);
	gtk_dialog_run(GTK_DIALOG(gp->getM_progress_dialog()));
	
	if( gp->getM_progress_dialog() != NULL ){
	  gtk_widget_destroy(gp->getM_progress_dialog());
	  gp->setM_progress_dialog(NULL);
	  // after, Forcibly stop thread 
	}

	// I reconstruct attribute view.
	GtkTreeStore* store 
	  = GTK_TREE_STORE(gtk_tree_view_get_model(gp->getM_attributeview()));
	gtk_tree_store_clear(store);
	gp->initializeAttributeView(store, true);

  }else if( NULL != strstr((char*)string,CAPTURE_DRAWWINDOW) ){
	std::string filename(gp->get_data_directory());
	filename += std::string("/capture.bmp");
	int height = gp->getM_rm()->getM_window_height();
	int width = gp->getM_rm()->getM_window_width();
	size_t memorysize = width * height;
	char *glpixeldata = new char[memorysize*4];
	unsigned int *pixeldata = new unsigned int[memorysize];
	memset(glpixeldata, 0, 4*memorysize*sizeof(char));
	memset(pixeldata, 0, memorysize*sizeof(unsigned int));
	

	// restore memory from draw window
	glPixelStorei(GL_PACK_ALIGNMENT ,1);
	glReadPixels(0,
				 0,
				 width,
				 height,
				 GL_RGBA,
				 GL_UNSIGNED_BYTE,
				 (void*)glpixeldata);

	for( int i = 0; i < height; i ++ ){
	  for( int j = 0; j < width; j ++ ){
		unsigned int R = (int)(glpixeldata[i*width*4+j*4+0]);
		unsigned int G = (int)(glpixeldata[i*width*4+j*4+1]);
		unsigned int B = (int)(glpixeldata[i*width*4+j*4+2]);
		unsigned int data = ((R << 16 )&0xFF0000)+((G << 8)&0xFF00)+B;
		//pixeldata[(height-1-i)*width+j] = data;
		pixeldata[i*width+j] = data;
	  }
	}
	
	// save bitmap file
	// create bitmap info header
	BITMAPINFO info;
	memset(&info,0,sizeof(BITMAPINFO));
	info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	info.bmiHeader.biWidth = width;
	info.bmiHeader.biHeight = height;
	info.bmiHeader.biPlanes = 1;
	info.bmiHeader.biBitCount = 32;
	library::graphics::SaveBitmapFile(filename, &info, pixeldata);
	delete [] glpixeldata;
	delete [] pixeldata;
	ShowMessageBox(std::string(APPLICATION_NAME) + std::string(" Message"),
				   std::string("Paths of created file is ") + filename);
  }



  GdkRectangle rect;
  rect = gp->getM_main_window()->allocation;
  gtk_widget_draw(GTK_WIDGET(gp->getM_main_window()),&rect);
}

/**
 * Callback of event to toggle line's checking
 * \note
 * Work is to toggle 3d model's drawing state.
 * And toggle menu checking.
 * @author r-suzuki
 * @date 2007-10-8
 * @version 1.1
 */
void cb_menu_line_toggled(GtkCheckMenuItem *checkmenuitem)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  GtkCheckMenuItem* item = checkmenuitem;
  if( gp->getM_model() == NULL ){
	return;
  }

  if(gtk_check_menu_item_get_active(item) ){
	gp->getM_model()->setM_state(gp->getM_model()->getM_state()
								 | GraphicalCommand::WIRE_FRAME);
  }else{
	gp->getM_model()->setM_state(gp->getM_model()->getM_state()
								 - GraphicalCommand::WIRE_FRAME);
  }
}


/**
 * Toggle to display FPS 
 * @author suzuki ryoutoku
 * @date 2008-6-20
 * @version 1.0
 */
void cb_menu_fps_toggled(GtkCheckMenuItem *checkmenuitem)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  GtkCheckMenuItem* item = checkmenuitem;
  if(gtk_check_menu_item_get_active(item) ){
	gp->getM_fps()->setM_state(0);
  }else{
	gp->getM_fps()->setM_state(1);
  }
}


/**
 * Callback for changing select target.
 * @author r-suzuki
 * @date 2008-12-2
 * @version 1.0
 */
void cb_menu_change_select(GtkCheckMenuItem *item, 
						   gpointer user_data)
{
  int param = (int)user_data;
  GraphicalObjectType type;
  GlobalParameter* gp = GlobalParameter::getInstance();
  Model* model = gp->getM_model();

  switch( param ){
  case 0:
	if( TRUE == gtk_check_menu_item_get_active(item) ){
	  cout << "change none" << endl;
	  type = library::graphics::NONE;
	  gp->set_selection(type);
	}
	break;
  case 1:
	if( TRUE == gtk_check_menu_item_get_active(item) ){
	  cout << "change vertex" << endl;
	  type = library::graphics::VERTEX;
	  GraphicalCommand::DrawingState state
		 = GraphicalCommand::GraphicalCommand::POINTS;
	  if( model != NULL )model->setM_state(model->getM_state()|state);
	}else{
	  type = library::graphics::NONE;
	  GraphicalCommand::DrawingState state
		 = GraphicalCommand::GraphicalCommand::POINTS;
	  if( model != NULL )model->setM_state(model->getM_state()-state);
	}
	gp->set_selection(type);
	break;
  case 2:
	if( TRUE == gtk_check_menu_item_get_active(item) ){
	  cout << "change polygon" << endl;
	  type = library::graphics::POLYGON;
	}else{
	  type = library::graphics::NONE;
	}
	gp->set_selection(type);
	break;
  }
}


/**
 * Callback of main window resize event
 * \note
 * This callback was set RenderingManager's target window.
 * Work is to correspond to resize event.
 * @author suzuki ryoutoku
 * @date 2007-8-17
 * @version 1.0
 */
void cb_size_allocate(GtkWidget * arg1, gpointer arg2, gpointer arg3)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  if( arg1 == gp->get_drawarea() ){
#ifdef DEBUG
	cout << "drawarea resize" << endl;
	cout << arg1->allocation.width << " " << arg1->allocation.height << endl;
#endif
	if( gp->getM_rm() != NULL ){
	  gp->getM_rm()->resize(arg1->allocation.width,
							arg1->allocation.height);
	  // change xwindow screen size
	  RECT tmp;
	  tmp.left = 10;
	  tmp.top = 10;
	  tmp.right = arg1->allocation.width - 20;
	  tmp.bottom = arg1->allocation.height - 20;
	  gp->getM_rm()->getM_screen(0)->setM_rect(tmp);
	  if( gp->getM_background() != NULL ){
		gp->getM_background()->setM_rect(0,
										 0,
										 tmp.right - tmp.left,
										 tmp.bottom - tmp.top);
	  }
	}
  }else if( arg1 == gp->getM_main_window() ){
#ifdef DEBUG
	cout << "window resize" << endl;
#endif
	// Now, This program have nothing to do.
  }
}


/**
 * This function's feture is to survey selection in tree views's column.
 * \note
 * This is test.
 * @author suzuki ryoutoku
 * @date 2007-8-15
 * @version 1.0
 */
void select_list(GtkTreeView *treeview)
{
  GtkTreeSelection *selection;

  selection = gtk_tree_view_get_selection(treeview);
  if (NULL == selection) return;
}


/**
 * Callback of click event
 * \note
 * Apply this function draw window.
 * @author suzuki ryoutoku
 * @date 2007-8-17
 * @version 1.0
 */
gboolean cb_button_press_event(GtkWidget* widget, 
							   GdkEventButton* event, 
							   gpointer data)
{
  GlobalParameter* gp = GlobalParameter::getInstance();

  if( gp->getM_keystate() == GDK_Control_L ||
	  GDK_Control_R == gp->getM_keystate() ){
	POINT point;
	if( gp->getM_model() == NULL )return false;
	if( gp->get_selection() != library::graphics::NONE ){
	  point.x = (long unsigned int)event->x;
	  point.y = (long unsigned int)event->y;
	  int index = gp->getM_rm()->selection(gp->get_selection(),
										   point,
										   gp->getM_model(),
										   gp->getM_rm()->getM_screen(0));
	  switch( gp->get_selection() ){
	  case library::graphics::POLYGON:
		gp->getM_model()->toggleSelectionPolygon(index);
		break;
	  case library::graphics::VERTEX:
		gp->getM_model()->toggleSelectionVertex(index);
		break;
	  }
	  gtk_widget_queue_draw(GTK_WIDGET(gp->getM_main_window()));
	}
  }
  return FALSE;
}

/**
 * Callback of event to be focused main window.
 * \note
 * Publish draw command.
 * This function was set root window.
 * @author suzuki ryoutoku
 * @date 2007-8-18
 * @version 1.0
 */
gboolean cb_focus_in_event(GtkWidget *,
						   GdkEvent *,
						   gpointer)
{
#ifdef DEBUG
  cout << "focuse in " << endl;
#endif
  GlobalParameter* gp = GlobalParameter::getInstance();
  gtk_widget_queue_draw(GTK_WIDGET(gp->getM_main_window()));
}


/**
 * Callback of event moiving mouse 
 * \note
 * Work is correspond to motion notify event.
 * If user press mouse button3, model rotate by trackball algorism.
 * If user press mouse button1, model move along x-axis and y-axis.
 * If user press mouse button2, model move along z-axis.
 * @author r-suzuki
 * @date 2007-9-29
 * @version 1.0
 */
gboolean cb_motion_notify_event(GtkWidget         *widget,
                                GdkEventMotion      *event)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  if( gp->getM_model() == NULL ) return false;
  double W = (double)(gp->getM_rm()->getM_window_width());
  double H = (double)(gp->getM_rm()->getM_window_height());
  double rate_x = 2.0f;
  double rate_y = 2.0f;
  static Quaternion<double> quaternion;
  if( event->state & GDK_BUTTON3_MASK){
	// Rotate by trackball
	double p1x = (     2.0f * ((double)gp->getM_before_x()) - W  ) / W;
	double p1y = ( H - 2.0f * ((double)gp->getM_before_y())      ) / H;
	double p2x = (     2.0f * ((double)event->x)             - W ) / W;
	double p2y = ( H - 2.0f * ((double)event->y)                 ) / H;
	quaternion *= Quaternion<double>::Trackball(p1x, p1y, p2x, p2y);
	Matrix<double> mat(quaternion);
	gp->getM_model()->getM_coordinate()->setM_matrix(mat);

	gp->setM_before_x(event->x);
	gp->setM_before_y(event->y);

	gtk_widget_queue_draw(GTK_WIDGET(gp->getM_main_window()));
  }else if(event->state & GDK_BUTTON1_MASK){
	gdouble x = event->x - gp->getM_before_x();
	gdouble y = event->y - gp->getM_before_y();
	double div = gp->getM_div();

	if( x > 0 ){
	  gp->getM_model()->getM_coordinate()->getM_pivot()->x+=div;
	}else if( x < 0 ){
	  gp->getM_model()->getM_coordinate()->getM_pivot()->x-=div;
	}
	if( y > 0 ){
	  gp->getM_model()->getM_coordinate()->getM_pivot()->y-=div;
	}else if( y < 0){
	  gp->getM_model()->getM_coordinate()->getM_pivot()->y+=div;
	}


	gp->setM_before_x(event->x);
	gp->setM_before_y(event->y);
	gtk_widget_queue_draw(GTK_WIDGET(gp->getM_main_window()));
  }else if(event->state & GDK_BUTTON2_MASK){
	gdouble z = event->y - gp->getM_before_z();
	gp->setM_before_z(event->y);
	double div = gp->getM_div();

	if( z > 0 ){
	  gp->getM_model()->getM_coordinate()->getM_pivot()->z-=div;
	}else if( z < 0){
	  gp->getM_model()->getM_coordinate()->getM_pivot()->z+=div;
	}
	gtk_widget_queue_draw(GTK_WIDGET(gp->getM_main_window()));
  }else{
	// mouse operation without drag 
	gp->setM_before_x(event->x);
	gp->setM_before_y(event->y);
  }
  
	
}


/**
 * Callback of event to toggle falg in tree view window's colum
 * \note
 * This tree shows hierarchy .
 * @author suzuki ryoutoku
 * @date 2007-10-16
 * @version 1.0
 */
void cb_status_toggled (GtkCellRendererToggle *renderer ,
						gchar *path_string ,
						gpointer user_data)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  GtkTreeModel *model;
  GtkTreeIter iter;
  GtkTreeIter parent;
  GtkTreePath *path;
  gboolean status;
  char* name;
  char *parent_name;
  gboolean ischild;
  
  model = gtk_tree_view_get_model(gp->getM_hierarchyview());
  path = gtk_tree_path_new_from_string(path_string);
  gtk_tree_model_get_iter(model,&iter,path);
  ischild = gtk_tree_model_iter_parent(model,&parent,&iter);

  if( !ischild ){
	// volume
	gtk_tree_model_get(model , &iter, 0 , &status, -1);
	gtk_tree_model_get(model , &iter, 1 , &name, -1);
    gtk_tree_store_set (GTK_TREE_STORE(model) , &iter ,
						0 , !status , -1);
#ifdef DEBUG
	cout << name << endl;
#endif
	
	if( gp->getM_model() == NULL ) return;

	PolygonBody* body = gp->getM_model()->getPolygonBody(name);
	if( body != NULL ){
	  body->set_state( body->get_state() ^ 0x01 );
	}

  }else{
	// group
	gtk_tree_model_get(model,&parent, 1,&parent_name,-1);
	gtk_tree_model_get(model , &iter, 0 , &status, -1);
	gtk_tree_model_get(model , &iter, 1 , &name, -1);
#ifdef DEBUG
	cout << "name = " << name << endl;
	cout << "parent name = " << parent_name << endl;
#endif

	PolygonBody* body = gp->getM_model()->getPolygonBody(parent_name);
	if( body != NULL ){
	  Group* group = body->getGroup(name);
	  group->set_state(group->get_state()^1);
	}
  }
  gtk_tree_store_set (GTK_TREE_STORE(model) , &iter ,
					  0 , !status , -1);

  gtk_tree_path_free (path);
  gtk_widget_queue_draw(GTK_WIDGET(gp->getM_main_window()));
}

/**
 * Callback of event to click Attribute window.
 * @author suzuki ryoutoku
 * @date 2007-10-18
 * @version 1.0
 */
gboolean cb_tree_item_double_clicked(GtkTreeView *treeview,
									 GtkTreePath *path,
									 GtkTreeViewColumn* column,
									 gpointer data)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  GtkTreeModel *model;
  GtkTreeIter iter;
  GtkTreeIter parent;
  char *name;
  char *parent_name;
  gboolean ischild;
  model = gtk_tree_view_get_model(treeview);
  gtk_tree_model_get_iter(model,&iter,path);
  gtk_tree_model_get(model,&iter,0,&name,-1);

#ifdef DEBUG
  cout << "child name = " << name << endl;
#endif

  ischild = gtk_tree_model_iter_parent(model,&parent,&iter);

  if( ischild ){

	  gtk_tree_model_get(model,&parent,0,&parent_name,-1);
#ifdef DEBUG
	  cout << "parent name = " << parent_name << endl;
#endif
  }

  if( gp->getM_model() == NULL ) return 0;
  if( !ischild ) return 0;

  
  // change color
  if( NULL != strstr(parent_name,"Color") ){
	Color<float> *color;
	Color<float> red(1.0,0.0,0.0,1.0);
	Color<float> blue(0.4,0.4,0.7,1.0);
	Color<float> green(0.4,0.7,0.4,1.0);
	Color<float> grey(0.7,0.7,0.7,1.0);
	Color<float> yellow(1.0,1.0,0.4,1.0);
	Color<float> white(1.0,1.0,1.0,1.0);
	Color<float> pink(1.0,0.8,0.8,1.0);
	
	if( NULL != strstr(name,"Red") ){
	  color = &red;
	}else if( NULL != strstr(name,"Blue") ){
	  color = &blue;
	}else if( NULL != strstr(name,"Green") ){
	  color = &green;
	}else if( NULL != strstr(name,"Grey") ){
	  color = &grey;
	}else if( NULL != strstr(name,"Yellow") ){
	  color = &yellow;
	}else if( NULL != strstr(name,"White") ){
	  color = &white;
	}else if( NULL != strstr(name,"Pink") ){
	  color = &pink;
	}
	gp->getM_model()->coloring(*color);
	
  }else if( NULL != strstr(parent_name,"Draw method") ){
	unsigned int draw_method = 0;
	if( NULL != strstr(name,"Vertex array") ){
	  draw_method = Model::VERTEX_ARRAY;

	}else if(NULL != strstr(name,"Triangle strip") ){
	  draw_method = Model::STRIP;

	}else if( NULL != strstr(name,"Strip with colors") ){
	  draw_method = Model::STRIP_WITH_COLOR;
	}
	gp->getM_model()->set_drawingmethod(draw_method);
  }
  gtk_widget_queue_draw(GTK_WIDGET(gp->getM_main_window()));
}


/**
 * Callback of event to change scroll bar  
 * @author suzuki ryoutoku
 * @date 2007-10-22
 * @version 1.0
 */
void cb_scaling(GtkScale* scale, gpointer data)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  int axis = (int)data;
  if(gp->getM_model()==NULL)return;
#ifdef DEBUG
  cout << "scaling = " << gtk_range_get_value(GTK_RANGE(scale)) << endl;
#endif

  double factor = gtk_range_get_value(GTK_RANGE(scale));
  Vector<double> svec = *(gp->getM_model()->getM_coordinate()->getM_scale());
  switch( axis ){
  case 0x00:
	svec.x=factor;
	break;
  case 0x01:
	svec.y=factor;
	break;
  case 0x02:
	svec.z=factor;
	break;
  }
  gp->getM_model()->getM_coordinate()->setM_scale(svec);
  

  gtk_widget_queue_draw(GTK_WIDGET(gp->getM_main_window()));
}

/**
 * Callback of event to press key board.
 * \note
 * This function is test.
 * @author suzuki ryoutoku
 * @date 2007-10-23
 * @version 1.0
 */
gboolean cb_key_press_event(GtkWidget *widget,
							GdkEventKey *event)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  if( GDK_Control_L == event->keyval ){
	gp->setM_keystate(GDK_Control_L);
  }else if( GDK_Control_R == event->keyval ){
	gp->setM_keystate(GDK_Control_L);
  }else if( GDK_Shift_L == event->keyval || 
			GDK_Shift_R == event->keyval ){
	// no future ... 
  }
  

  return TRUE;
}

/**
 * Callback of event to release key board.
 * \note
 * This function is test.
 * @author suzuki ryoutoku
 * @date 2007-10-24
 * @version 1.0
 */
gboolean cb_key_release_event(GtkWidget *widget,
							  GdkEventKey *event)
{
  if( GDK_Control_L == event->keyval ||
	  GDK_Control_R == event->keyval){
	GlobalParameter* gp = GlobalParameter::getInstance();
	gp->setM_keystate(0);
  }

  return TRUE;
}

/**
 * Callback of event mouse scroll action.
 * \note
 * If user's mouse have note scroll feature, work is unenable.
 *
 * @param widget
 * @param event
 *
 * @return Only TRUE
 *
 * @author suzuki ryoutoku
 * @date 2007-10-23
 * @version 1.0
 */
gboolean cb_scroll_event(GtkWidget *widget,
						 GdkEventScroll *event)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  double div = gp->getM_div();
  if( gp->getM_model() == NULL ) return false;
  if( event->direction == GDK_SCROLL_UP ){
	gp->getM_model()->getM_coordinate()->getM_pivot()->z-=div;
  }else if( event->direction == GDK_SCROLL_DOWN ){
	gp->getM_model()->getM_coordinate()->getM_pivot()->z+=div;
  }
  gtk_widget_queue_draw(GTK_WIDGET(gp->getM_main_window()));
  return TRUE;
}



/**
 * This method is equiped in a thread.
 * \note
 * Thread builded will start to create triangle strip from model data.
 *
 * @author suzuki ryoutoku
 * @version 1.0
 * @date 2008-1-10
 */
void* thread_function(void* args)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  for( int i = 0; i < gp->getM_model()->getPolygonBodySum(); i++){
	PolygonBody* body = gp->getM_model()->getPolygonBody(i);
	StripCreator strip(LogManager::GetInstance());
	// user input
	StripCreatingOption sco(body, 
							gp->get_strip_start_select());
	strip.createTriangleStrip(&sco);

	gdk_threads_enter();
	{
	  double per=(double)(i+1)/(double)(gp->getM_model()->getPolygonBodySum());
	  GtkProgressBar* pb = (GtkProgressBar*)(gp->getM_progress());
	  gdouble new_val = per;
	  cout << "now value=" << gtk_progress_bar_get_fraction(pb) << endl;
	  gtk_progress_bar_set_fraction(pb,new_val);
	  gdk_flush();
	}
	gdk_threads_leave();
  }

  if( NULL != gp->getM_progress_dialog() ){
	gdk_threads_enter();
	{
	  gtk_widget_destroy(gp->getM_progress_dialog());
	  gp->setM_progress_dialog(NULL);
	}
	gdk_threads_leave();
  }

#if 0
  gp->getM_model()->setM_strip_flag(true);
#endif

  return NULL;
}



void TestFunction(library::graphics::Screen* screen)
{
  GLint vp[4];

  // set polygon mode
  ::glEnable( GL_POLYGON_OFFSET_FILL );
  ::glPolygonOffset( 0.5, 0.5 );
  ::glPolygonMode( GL_FRONT, GL_FILL );

  // setting my coordinate
  ::glMatrixMode(GL_MODELVIEW);
  ::glPushMatrix();
  ::glLoadIdentity();
  
  // enable transparent
  ::glAlphaFunc(GL_GREATER, 0.5);// when alpha less than 0xFF>>1
  ::glEnable(GL_ALPHA_TEST); 

  Color<float> color2(0.0, 0.0, 0.0, 0.0);
  ::glMaterialfv(GL_FRONT,GL_AMBIENT,  color2.color);
  Color<float> color3(0.0, 0.0, 0.0, 0.0);
  ::glMaterialfv(GL_FRONT,GL_SPECULAR, color3.color);
  // enable variable material color within glBegin~glEnd
  ::glEnable( GL_COLOR_MATERIAL );
  // variable color is diffuse
  ::glColorMaterial(GL_FRONT, GL_DIFFUSE);
  // enable lighting
  ::glEnable( GL_LIGHTING );
  

  // if you want semi transparency, set a to 0.6, 0.5, 0.4...
  ::glMatrixMode(GL_MODELVIEW);
  ::glLoadIdentity();

  ::glMatrixMode(GL_MODELVIEW);

  ::glColor3d( 1.0, 1.0, 0.4);
  ::glBegin(GL_TRIANGLE_STRIP);
  {
	::glNormal3d(0.0,0.0,1.0);
	::glVertex3d(0.0,
				 0.0,
				 1.0);
	
	::glVertex3d(1.0,
				 0.0,
				 1.0);

	::glVertex3d(0.0,
				 1.0,
				 1.0);

	::glVertex3d(0.0,
				 0.0,
				 1.0);

	::glNormal3d(0.0,0.0,1.0);
	::glVertex3d(-1.0,
				 1.0,
				 1.0);
  }
  ::glEnd();

  
  // disable testing alpha
  ::glDisable(GL_ALPHA_TEST); 
  // cancel depth buffer
  ::glClear( GL_DEPTH_BUFFER_BIT );

  ::glMatrixMode(GL_MODELVIEW);
  ::glPopMatrix();
}


/**
 * @author suzuki ryoutoku
 * @version 1.0
 * @date 2008-4-23
 */
GtkWidget* CreateMainWindow(void)
{
  GtkWidget* mainwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_widget_add_events(mainwindow, GDK_FOCUS_CHANGE_MASK );
  // Setting style root window.
  gtk_window_set_title(GTK_WINDOW(mainwindow), APPLICATION_NAME);
  // Setting root window size
  gtk_widget_set_size_request(mainwindow, 
							  MAIN_WINDOW_WIDTH,
							  MAIN_WINDOW_HEIGHT);

  g_signal_connect(G_OBJECT(mainwindow), 
				   "destroy",
				   G_CALLBACK(gtk_main_quit),
				   NULL);
  g_signal_connect(GTK_WIDGET(mainwindow), 
				   "size-allocate",
                   G_CALLBACK(cb_size_allocate), NULL);

  // Equip root window with callback for focus in
  g_signal_connect(G_OBJECT(mainwindow),
				   "focus_in_event",
				   G_CALLBACK(cb_focus_in_event),
				   NULL);

  // Equip root window with callback keyboard event
  g_signal_connect(G_OBJECT(mainwindow),
				   "key_press_event",
				   G_CALLBACK(cb_key_press_event),
				   NULL);
  // Equip root window with callback keyboard event
  g_signal_connect(G_OBJECT(mainwindow),
				   "key_release_event",
				   G_CALLBACK(cb_key_release_event),
				   NULL);

  return mainwindow;
}

/**
 * This function is creating main menu bar of main window and sub menu equiped.
 * @author suzuki ryoutoku
 * @version 1.0
 * @date 2008-4-23
 */
GtkWidget* CreateMenuBar(void)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  GtkWidget* menu = gtk_menu_bar_new();
  // 'File' main menu bar item, 'File' have sub menu bar.
  GtkWidget* fileitem = gtk_menu_item_new_with_label(MENU_FILE);

  // 'Display' main menu bar item, 'Display' have sub menu bar.
  GtkWidget* displayitem = gtk_menu_item_new_with_label(MENU_DISPLAY);

  // 'Selection' main menu bar item, 'Selection' have sub menu bar.
  GtkWidget* selectionitem = gtk_menu_item_new_with_label(MENU_SELECTION);

  // 'Edit' is itme of main menu bar, 'Edit' have sub menu bar.
  GtkWidget* edititem = gtk_menu_item_new_with_label(MENU_EDIT);

  // 'Help' main menu bar item.
  GtkWidget* helpitem = gtk_menu_item_new_with_label(MENU_HELP);
  
  // Add items to menu bar
  gtk_menu_bar_append(GTK_MENU_BAR(menu), fileitem);
  gtk_menu_bar_append(GTK_MENU_BAR(menu), displayitem);
  gtk_menu_bar_append(GTK_MENU_BAR(menu), selectionitem);
  gtk_menu_bar_append(GTK_MENU_BAR(menu), edititem);
  gtk_menu_bar_append(GTK_MENU_BAR(menu), helpitem);
  
  // Creating 'File' submenu contents
  GtkWidget* submenu = gtk_menu_new();

  GtkWidget* submenu_item;
  {
	submenu_item = gtk_menu_item_new_with_label(OPEN_3DSFILE_MENU);
	gtk_menu_append(GTK_MENU(submenu), submenu_item);
	// Setting callback function
	gtk_signal_connect_object (GTK_OBJECT (submenu_item), 
							   "activate",
							   GTK_SIGNAL_FUNC(cb_menuitem_response), 
							   (void*)OPEN_3DSFILE_MENU);
  }
  {
	submenu_item = gtk_menu_item_new_with_label(OPEN_VDFFILE_MENU);
	gtk_menu_append(GTK_MENU(submenu), submenu_item);
	// Setting callback function
	gtk_signal_connect_object (GTK_OBJECT (submenu_item), 
							   "activate",
							   GTK_SIGNAL_FUNC(cb_menuitem_response), 
							   (void*)OPEN_VDFFILE_MENU);
  }
  {
	submenu_item = gtk_menu_item_new_with_label(OPEN_PCMFILE_MENU);
	gtk_menu_append(GTK_MENU(submenu), submenu_item);
	// Setting callback function
	gtk_signal_connect_object (GTK_OBJECT (submenu_item), 
							   "activate",
							   GTK_SIGNAL_FUNC(cb_menuitem_response), 
							   (void*)OPEN_PCMFILE_MENU);
  }
  {
	submenu_item = gtk_menu_item_new_with_label(SUB_MENU_OUTPUT_PCMFILE);
	gtk_menu_append(GTK_MENU(submenu), submenu_item);
	// Setting callback function
	gtk_signal_connect_object(GTK_OBJECT(submenu_item), 
							  "activate",
							  GTK_SIGNAL_FUNC(cb_menuitem_response), 
							  (void*)SUB_MENU_OUTPUT_PCMFILE);
  }
  {
	submenu_item = gtk_menu_item_new_with_label(SUB_MENU_OUTPUT_VDFFILE);
	gtk_menu_append(GTK_MENU(submenu), submenu_item);
	// Setting callback function
	gtk_signal_connect_object(GTK_OBJECT(submenu_item), 
							  "activate",
							  GTK_SIGNAL_FUNC(cb_menuitem_response), 
							  (void*)SUB_MENU_OUTPUT_VDFFILE);
  }
  {
	submenu_item = gtk_menu_item_new_with_label(CAPTURE_DRAWWINDOW);
	gtk_menu_append(GTK_MENU(submenu), submenu_item);
	// Setting callback function
	gtk_signal_connect_object (GTK_OBJECT (submenu_item), 
							   "activate",
							   GTK_SIGNAL_FUNC(cb_menuitem_response), 
							   (void*)CAPTURE_DRAWWINDOW);
  }
  // To associate submenu with main menu's item
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileitem),submenu);



  // Creating 'Display' submenu contents
  submenu = gtk_menu_new();
  submenu_item
	= gtk_check_menu_item_new_with_label("Display polygon line");

  gp->setM_line_menu(submenu_item);
  // Above code is call the method to create check item
  gtk_menu_append(GTK_MENU(submenu), submenu_item);

  // Setting callback for cheking on or off
  gtk_signal_connect_object(GTK_OBJECT(submenu_item), 
							"toggled",
							GTK_SIGNAL_FUNC(cb_menu_line_toggled), 
							(void*)submenu_item);
  gtk_check_menu_item_set_active((GtkCheckMenuItem*)submenu_item, FALSE);
  
  // Setting Light parameter's menu
  submenu_item =gtk_menu_item_new_with_label(SUB_MENU_SETTING_LIGHT_PARAMETER);
  gtk_menu_append(GTK_MENU(submenu), submenu_item);
  // To equip callback with selection item.
  gtk_signal_connect_object (GTK_OBJECT (submenu_item), 
							 "activate",
							 GTK_SIGNAL_FUNC(cb_menuitem_response), 
							 (void*)SUB_MENU_SETTING_LIGHT_PARAMETER);

  // Setting reset coordinate's menu
  submenu_item = gtk_menu_item_new_with_label(SUB_MENU_RESET_COORDINATE);
  gtk_menu_append(GTK_MENU(submenu), submenu_item);
  gtk_signal_connect_object (GTK_OBJECT (submenu_item), 
							 "activate",
							 GTK_SIGNAL_FUNC(cb_menuitem_response), 
							 (void*)SUB_MENU_RESET_COORDINATE);

  // Setting scaling 's menu
  submenu_item = gtk_menu_item_new_with_label(SUB_MENU_SCALING);
  gtk_menu_append(GTK_MENU(submenu), submenu_item);
  gtk_signal_connect_object(GTK_OBJECT (submenu_item), 
							"activate",
							GTK_SIGNAL_FUNC(cb_menuitem_response), 
							(void*)SUB_MENU_SCALING);

  // Setting toggle fps menu
  submenu_item = gtk_check_menu_item_new_with_label(SUB_MENU_TOGGLE_FPS);
  gtk_menu_append(GTK_MENU(submenu), submenu_item);
  gtk_check_menu_item_set_active((GtkCheckMenuItem*)submenu_item, FALSE);
  gtk_signal_connect_object(GTK_OBJECT(submenu_item), 
							"toggled",
							GTK_SIGNAL_FUNC(cb_menu_fps_toggled), 
							(void*)submenu_item);
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(displayitem),submenu);

  // Creating 'Selection' menu contents
  submenu = gtk_menu_new();
  submenu_item = gtk_radio_menu_item_new_with_label(NULL, SUB_MENU_NONE);
  gtk_menu_append(GTK_MENU(submenu), submenu_item);
  GSList* group = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(submenu_item));
  gtk_signal_connect(GTK_OBJECT(submenu_item), 
					 "toggled",
					 GTK_SIGNAL_FUNC(cb_menu_change_select),
					 (void*)0x00);

  submenu_item = gtk_radio_menu_item_new_with_label(group, SUB_MENU_VERTEX);
  gtk_menu_append(GTK_MENU(submenu), submenu_item);
  group = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(submenu_item));
  gtk_signal_connect(GTK_OBJECT(submenu_item), 
					 "toggled",
					 GTK_SIGNAL_FUNC(cb_menu_change_select),
					 (void*)0x01);
  gp->set_check_selectvert(submenu_item);
  
  submenu_item = gtk_radio_menu_item_new_with_label(group, SUB_MENU_POLYGON);
  gtk_menu_append(GTK_MENU(submenu), submenu_item);
  gtk_signal_connect(GTK_OBJECT(submenu_item), 
					 "toggled",
					 GTK_SIGNAL_FUNC(cb_menu_change_select),
					 (void*)0x02);
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(selectionitem),submenu);
  gp->set_check_selectpoly(submenu_item);
  
  // Creating 'Edit' menu contents
  submenu = gtk_menu_new();

  submenu_item = gtk_menu_item_new_with_label(SUB_MENU_CREATE_TRIANGLESTRIP);
  gtk_menu_append(GTK_MENU(submenu), submenu_item);

  // To equip callback , event is selection submenu item.
  gtk_signal_connect_object (GTK_OBJECT (submenu_item), 
							 "activate",
							 GTK_SIGNAL_FUNC(cb_menuitem_response), 
							 (void*)SUB_MENU_CREATE_TRIANGLESTRIP);
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(edititem),submenu);


  // Creating 'Help' menu contents
  submenu = gtk_menu_new();

  submenu_item = gtk_menu_item_new_with_label(SUB_MENU_ABOUT_STRIPEXPERIMENT);
  gtk_menu_append(GTK_MENU(submenu), submenu_item);

  // To equip callback , event is selection submenu item.
  gtk_signal_connect_object (GTK_OBJECT (submenu_item), 
							 "activate",
							 GTK_SIGNAL_FUNC(cb_menuitem_response), 
							 (void*)SUB_MENU_ABOUT_STRIPEXPERIMENT);
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(helpitem),submenu);


  return menu;
}


/**
 * This method's work is like Windows' MessageBox
 * @author r-suzuki
 * @date 2009-1-10
 * @version 1.0
 */
bool ShowMessageBox(std::string title, std::string message)
{
  GlobalParameter* gp = GlobalParameter::getInstance();
  GtkDialogFlags flag=(GtkDialogFlags)(GTK_DIALOG_MODAL
									   | GTK_DIALOG_DESTROY_WITH_PARENT);
  GtkWidget* dialog 
	= gtk_dialog_new_with_buttons(title.c_str(),
								  GTK_WINDOW(gp->getM_main_window()),
								  flag,
								  NULL);
  GtkWidget* label = gtk_label_new(message.c_str());
  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox),
					label);
  gtk_widget_show_all(dialog);
  gint response = gtk_dialog_run(GTK_DIALOG(dialog));
  return true;
}
